package Cluster;

import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;

public class ClusteringProcess {
	
	public static final int MATRIC_DTW = 1;
	public static final int NEW_CLUSTER = -1;
	protected ArrayList<ClusterBulk> listClusterb = null;
	
	public ClusteringProcess() {
		this.listClusterb = new ArrayList<ClusterBulk>();
	}
	
	protected void __001_addToCluster(Trajectory traj, int indexCluster) {
		if(indexCluster == NEW_CLUSTER) {  //create new cluster
			this.listClusterb.add(new ClusterBulk(this.listClusterb.size(),0));
			this.listClusterb.get(this.listClusterb.size() - 1).ACT001_insertNewTraj(traj);
		}
		else {
			this.listClusterb.get(indexCluster).ACT001_insertNewTraj(traj);
		}
	}
	
	protected int __002_clusterComparison(Trajectory traj, int whichMatric, double maxDist, double maxDistThreshold) {
		int insertClusterIndex = -1;
		double curMinDist = maxDist + 1;
		int curMinClusterIndex = 0;
		int indexCurCluster = 0;
		while(indexCurCluster < this.listClusterb.size()) {
			switch(whichMatric) {
			case MATRIC_DTW: //do DTW metric
				double matricResult = Matric.DTW(traj, this.listClusterb.get(indexCurCluster).mainTraj);
				if(matricResult < curMinDist) {
					curMinDist = matricResult;
					curMinClusterIndex = indexCurCluster;
				}
				break;
			}
			indexCurCluster = indexCurCluster + 1;
		}
		if(curMinDist / maxDist > maxDistThreshold) {  //if no similar cluster, create new one
			insertClusterIndex = NEW_CLUSTER;
		}
		else {
			insertClusterIndex = curMinClusterIndex;
		}
		return insertClusterIndex;
	}
	
	public void ACT001_doCluster(int whichMatric, double maxDist, double maxDistThreshold, 
			ArrayList<Trajectory> listTraj) {
		int indexTraj = 0;
		
		while(indexTraj < listTraj.size()) {
			if(indexTraj == 0) {  //first trajectory
				this.__001_addToCluster(listTraj.get(indexTraj), ClusteringProcess.NEW_CLUSTER);
			}
			else {
				this.__001_addToCluster(listTraj.get(indexTraj), this.__002_clusterComparison(listTraj.get(indexTraj), whichMatric, maxDist, maxDistThreshold));
			}
			if(indexTraj % 1000 == 0) {
				System.out.println(indexTraj + "is done");
			}
			indexTraj = indexTraj + 1;
		}
	}
	
	public void ACT002_showResult() {
		int indexCluster = 0;
		FileWriter fw;
		try {
			fw = new FileWriter("draw.txt");
			while(indexCluster < this.listClusterb.size()) {
				ClusterBulk cb = this.listClusterb.get(indexCluster);
				System.out.println("Cluster ID : " + cb.clusterID);
				int[] cRange = cb.GET003_clusterRange();
				fw.append(cRange[0] + " " + cRange[1] + " " + cRange[2] + " " + cRange[3] + "\n");
				ArrayList<Trajectory> listTraj = cb.GET002_listTraj();
				int indexTraj = 0;
				while(indexTraj < listTraj.size()) {
					System.out.print(listTraj.get(indexTraj).traj_id + " ");
					fw.append(listTraj.get(indexTraj).traj_id + " ");
					indexTraj = indexTraj + 1;
				}
				System.out.println();
				fw.append("\n");
				indexCluster = indexCluster + 1;
			}
			System.out.println("MaxDistance = " + Matric.maxDist);
			
			fw.flush();
			fw.close();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
